#/usr/bin/python27
#-*- coding: utf-8 -*-
#  Copyright 2011-2013 wuweihui@cn.ibm.com
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import os, re

class MOFClass(object):
   def __init__(self, cn, fn, sl, el, parent=''):
      self.name = cn
      self.fn = fn
      self.lwname = self.name.lower()
      self.description = ''
      self.start = sl
      self.end = el
      self.parent = parent
      self.args = []
      self.functions = []
      self.init_attr()
      self.init_value_maps()
      
   def get_src(self):
      try:
         with open(self.fn, 'rb') as fp:
            return fp.read()[self.start:self.end]
      except Exception, e:
         return ''
         
   def init_attr(self):
      src = self.get_src()
      if src.find('\r\n') != -1:
         src = src.replace('\r\n', '\n')
      #if not isinstance(src, str): print self.fn
      re_keyname = re.compile(r'\s*(\[\w+\])*\s*([a-zA-Z]\w+)\s+(REF)*\s*([a-zA-Z]\w+\[*\d*\]*)\s*\;|\s*(\[\w+\])*\s*([a-zA-Z]\w+)\s+([a-zA-Z]\w+\[*\d*\]*)\s*\=\s*(.*?)\s*\;')
      re_function = re.compile(r'\s*([a-zA-Z]\w+)\s+([a-zA-Z]\w+)\s*\(')
      re_endfunc = re.compile(r'.*?\);\s*$')
      re_partype = re.compile(r'\s*\[(\w+xtension\("[\d\.]+"\),)*\s*(IN,\s*OUT|IN|OUT)(,|\])')
      re_par = re.compile(r'\s*(\[\w+\])*\s*([a-zA-Z]\w+)\s+(REF)*\s*([a-zA-Z]\w+)\[*\]*\s*(,|\)\;)\s*$')
      
      lines = src.splitlines()
      funcflag = False
      partype = argtype = argname = ''
      for i in range(len(lines)):
         line = lines[i]
         key_ret = re_keyname.match(line)
         func_ret = re_function.match(line)
         if key_ret:
            group = key_ret.groups()
            #print group
            vartype = group[1] or group[5]
            varname = group[3] or group[6]
            varvalue = group[7]
            self.args.append(MOFParameter(vartype, varname, varvalue, start=src.index(key_ret.group())))
         if func_ret:
            functype, funcname = func_ret.groups()
            partype = argtype = argname = ''
            moffunc = MOFFunction(type=functype, name=funcname, start=src.index(func_ret.group()))
            funcflag = True
            line = line.replace(func_ret.group(), '')
            
         if funcflag:
            partype_ret = re_partype.match(line)
            par_ret = re_par.match(line)
            if partype_ret:
               group = partype_ret.groups()
               partype = group[1].replace(',', '').replace(' ', '')
            if par_ret:
               group = par_ret.groups()
               argtype = group[1]
               argname = group[3]
            if argtype and argname:
               moffunc.args.append(MOFParameter(argtype, argname, io=partype, start=src.index(par_ret.group(), moffunc.start)))
               partype = argtype = argname = ''
            if re_endfunc.match(line):
               funcflag = False
               self.functions.append(moffunc)
               
               
   def init_value_maps(self):
      """
      ValueMap { "0", "1", "2", "3", "4", "5", "6", ".."},
          Values { "Job Completed with No Error", "Not Supported",
              "Unknown", "Timeout", "Failed", "Invalid Parameter",
              "In Use", "DMTF Reserved"}
      """
      re_valuemap = re.compile(r'(\walue\wap\s*\{([^\[\{]*?)\}\,*\s*\walues\s*\{([^\[\{]*?)\}|\walues\s*\{([^\[\{]*?)\}\,*\s*\walue\wap\s*\{([^\[\{]*?)\})', re.DOTALL)
      src = self.get_src()
      maplist = re_valuemap.findall(src)
      stpos = 0
      for ss, lks, lvs, rvs, rks in maplist:
         #print ss
         ks = lks or rks
         vs = lvs or rvs
         po = src.index(ss, stpos)
         stpos = po + len(ss)
         for func in self.functions:
            if func.start > po:
               func.errordict = {}
               break
         if self.functions and func.start > po:
            ksl = []
            vsl = []
            for item in ks.splitlines():
               for i in item.strip().split(','):
                  if i and not i.strip().startswith('//'):
                     ksl.append(i.strip())
            for item in vs.splitlines():
               for i in item.strip().split(','):
                  if i and not i.strip().startswith('//'):
                     vsl.append(i.strip())
            
            for i in range(len(ksl) < len(vsl) and len(ksl) or len(vsl)):
               func.errordict[ksl[i].replace('"', '')] = vsl[i].replace('"', '')
               
def mof_class_cmp(a, b):
   if a.lwname > b.lwname:
      return 1
   elif a.lwname < b.lwname:
      return -1
   else:
      return 0
      
class MOFFunction(object):
   def __init__(self, **kws):
      self.type = ''
      self.description = ''
      self.name = ''
      self.args = []
      self.start = 0
      self.errordict = {}
      if kws:
         for k, v in kws.items():
            try:
               self.__setattr__(k, v)
            except:
               pass
               
class MOFParameter(object):
   def __init__(self, type, name, default='', io='', start='', dsp=''):
      self.type = type
      self.io = io
      self.name = name
      self.description = dsp
      self.default = default
      self.start = start
      
      
      
def read_mof(fn):
   mcl = []
   with open(fn, 'rb') as fp:
      src = fp.read()
      
   re_classname = re.compile(r'(class\s+(\w+)\s*\{|class\s+(\w+)\s*\:\s*(\w+)\s*\{)')
   classlist = re_classname.findall(src)
   for i in range(len(classlist)):
      cn = classlist[i][1] or classlist[i][2]
      basecn = classlist[i][3]
      sl = src.index(classlist[i][0])
      try:
         sl = src.rindex('\n\n', 0, sl)
      except ValueError, e:
         try:
            sl = src.rindex('\r\n\r\n', 0, sl)
         except ValueError, e:
            sl = 0
      if i + 1 == len(classlist):
         el = len(src)
      else:
      #nextcn = classlist[i + 1][1] or classlist[i + 1][2]
      #print nextcn
         el = src.index(classlist[i + 1][0])
         try:
            el = src.rindex('\n\n', 0, el)
         except ValueError, e:
            try:
               el = src.rindex('\r\n\r\n', 0, el)
            except ValueError, e:
               el = len(src)
               
      mcl.append(MOFClass(cn, fn, sl, el, basecn))
   return mcl
   
   
   
if __name__ == '__main__':
   pass